package org.simpleframework.aop;

import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParameter;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.ShadowMatch;

import java.lang.reflect.Method;

/**
 * 解析Apect表达式并且定位被织入的目标
 * @ClassName PointcutLocator
 * @Description
 * @Author 47980
 * @Date 2020/8/11 6:33
 * @Version V_1.0
 **/
public class PointcutLocator {
    /**
     * Pointcut解析器，直接给它赋值上AspectJ的所以表达式，以便支持对众多表达式的解析
     */
    private PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
            PointcutParser.getAllSupportedPointcutPrimitives()
    );

    /**
     * 表达式解析器
     */
    private PointcutExpression pointcutExpression;
    public PointcutLocator(String expression) {
        this.pointcutExpression = pointcutParser.parsePointcutExpression(expression);
    }

    /**
     * 判断传入的class对象是否是Aspect的目标代理对象，即匹配Pointcut表达式(初筛)
     * @param targetClass
     * @return
     */
    public boolean roughMatches(Class<?> targetClass) {
        // couldMatchJoinPointsInType 比较坑
        // 不能校验 （execution， call，get，set） 面对无法校验的表达式，返回false
        return pointcutExpression.couldMatchJoinPointsInType(targetClass);
    }

    /**
     * 判断传入的class对象是否是Aspect的目标代理对象，即匹配Pointcut表达式(精筛)
     * @param method
     * @return
     */
    public boolean accurateMatches(Method method) {
        ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
        if (shadowMatch.alwaysMatches()) {
            return true;
        } else {
            return false;
        }
    }
}
